{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "3509e851-c4c3-4feb-8999-340b26b68600",
   "metadata": {},
   "source": [
    "# Exponentiation\n",
    "\n",
    "The exponentiation function produces a quantum gate that approximates the exponentiation, $\\exp(-iHt)$, of any input Hermitian operator, $H$. The Classiq engine automatically generates an efficient higher-order Trotter-Suzuki quantum program [ [1] ](#Trotter-Suzuki) that minimizes the functional error and satisfies a given local constraint on the depth. The functional error is measured by the operator norm [ [2] ](#operator-norm) and evaluated according to Ref. [[3]](#error-bound)\n",
    "\n",
    "The Hamiltonian is given as any $n$-qubit operator in its Pauli basis [[4]](#pauli-basis):\n",
    "$$\n",
    "H=\\sum_i c_i\\left[\\sigma_{j_{1,i}}\\otimes\\sigma_{j_{2,i}}\\otimes\\cdots\\otimes\\sigma_{j_{n,i}}\\right],\n",
    "$$\n",
    "where $\\sigma_{0,1,2,3}=I,X,Y,Z$ are the single-qubit Pauli operators, and $j\\in\\{0,1,2,3\\}$, and $c_i$ are complex coefficients.\n",
    "For example, the operator $H=0.1\\cdot I\\otimes Z+0.2\\cdot X\\otimes Y$ is input as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "a6d52a3e-3f5a-43d4-af4e-c1e9f9be559d",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:24:27.437764Z",
     "iopub.status.busy": "2024-05-07T13:24:27.436507Z",
     "iopub.status.idle": "2024-05-07T13:24:30.374160Z",
     "shell.execute_reply": "2024-05-07T13:24:30.373520Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq import Pauli, PauliTerm\n",
    "\n",
    "pauli_list = [\n",
    "    PauliTerm(pauli=[Pauli.I, Pauli.Z], coefficient=0.1),\n",
    "    PauliTerm(pauli=[Pauli.X, Pauli.Y], coefficient=0.2),\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9c9febbd-4593-42b9-b443-a4fde60e088c",
   "metadata": {},
   "source": [
    "Function: `exponentiation_with_depth_constraint`\n",
    "\n",
    "Arguments:\n",
    "\n",
    "* `pauli_operator`: `CArray[PauliTerm]` - the Hamiltonian to exponentiate as described above,\n",
    "* `evolution_coefficient`: `CReal` - a global evolution coefficient (the parameter $t$ above),\n",
    "* `max_depth`: `CInt` - a maximal depth for the implementation,\n",
    "* `qbv`: `QArray[QBit]` - the quantum state on which we apply the evolution."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eb6eafb6-66b3-400d-a044-906446ab551f",
   "metadata": {},
   "source": [
    "## Example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "d10f9e15-bca1-4cf4-9578-e054ebc2d760",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:24:30.377326Z",
     "iopub.status.busy": "2024-05-07T13:24:30.376686Z",
     "iopub.status.idle": "2024-05-07T13:24:32.680281Z",
     "shell.execute_reply": "2024-05-07T13:24:32.679588Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq import (\n",
    "    Output,\n",
    "    Pauli,\n",
    "    PauliTerm,\n",
    "    QArray,\n",
    "    QBit,\n",
    "    allocate,\n",
    "    create_model,\n",
    "    exponentiation_with_depth_constraint,\n",
    "    qfunc,\n",
    "    synthesize,\n",
    "    write_qmod,\n",
    ")\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def main(qba: Output[QArray[QBit]]):\n",
    "\n",
    "    allocate(4, qba)\n",
    "    exponentiation_with_depth_constraint(\n",
    "        [\n",
    "            PauliTerm(pauli=[Pauli.X, Pauli.X, Pauli.I, Pauli.I], coefficient=0.1),\n",
    "            PauliTerm(pauli=[Pauli.Y, Pauli.Y, Pauli.I, Pauli.I], coefficient=0.2),\n",
    "            PauliTerm(pauli=[Pauli.Z, Pauli.Z, Pauli.Y, Pauli.X], coefficient=0.4),\n",
    "            PauliTerm(pauli=[Pauli.I, Pauli.I, Pauli.I, Pauli.X], coefficient=0.4),\n",
    "        ],\n",
    "        evolution_coefficient=0.05,\n",
    "        max_depth=50,\n",
    "        qbv=qba,\n",
    "    )\n",
    "\n",
    "\n",
    "qmod = create_model(main)\n",
    "write_qmod(qmod, \"exponentiation\")\n",
    "qprog = synthesize(qmod)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "81411696-003b-4ecb-977b-a5752c7ca1e8",
   "metadata": {},
   "source": [
    "## References\n",
    "\n",
    "<!-- prettier-ignore-start -->\n",
    "<a name=\"Trotter-Suzuki\">[1]</a> N. Hatano and M. Suzuki, Finding Exponential Product Formulas of Higher Orders, [https://arxiv.org/abs/math-ph/0506007](https://arxiv.org/abs/math-ph/0506007) (2005).\n",
    "\n",
    "\n",
    "\n",
    "<a name=\"operator-norm\">[2]</a> [https://en.wikipedia.org/wiki/Operator_norm](https://en.wikipedia.org/wiki/Operator_norm)\n",
    "\n",
    "<a name=\"error-bound\">[3]</a> A. M. Childs et al, Toward the first quantum simulation with quantum speedup, [https://arxiv.org/abs/1711.10980](https://arxiv.org/abs/1711.10980) (2017).\n",
    "\n",
    "<a name=\"pauli-basis\">[4]</a> [https://en.wikipedia.org/wiki/Generalizations_of_Pauli_matrices#Multi-qubit_Pauli_matrices_(Hermitian)](https://en.wikipedia.org/wiki/Generalizations_of_Pauli_matrices#Multi-qubit_Pauli_matrices_(Hermitian))\n",
    "<!-- prettier-ignore-end -->"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
